#include "DataCenter.h"
#include "StdSqlite3.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <openssl/sha.h>
#include <openssl/md5.h>


#define DBPath "./chatroom.db"

// 你想被所有的函数共享，但又不希望在外部出现他，定义一个全局变量，然后封锁在本文件内部
static SQL *s;

bool DataCenterInit()
{
    // 第一步先打开数据库
    s = StdSqlite3Init(DBPath);
    if (s == NULL)
    {
        return false;
    }

    // 用户表的创建
    char sql[] = "create table if not exists user(name text primary key,passwd text not null, salt text not null);";
    // if (SQLExec(s, sql) == false)
    // {
    //     return false;
    // }
    // return true;
    return SQLExec(s, sql);
}

// 判断用户是否存在
bool IsUserExist(const char *name)
{
    char sql[1024] = { 0 };
    // 用名字查
    sprintf(sql, "select count(*) from user where name = '%s';", name);
    char **result = GetTableInfo(s, sql, NULL, NULL);
    if (result == NULL)
        return false;
    int count = atoi(result[1]);
    FreeTableInfo(result);
    return count != 0;
}

// 随机生成盐值
char* GenerateSalt()
{
    srand((unsigned)time(NULL));
    char salt[16] = { 0 };
    for (int i = 0; i < 16; i++)
    {
        salt[i] = rand() % 95 + 32;
    }
    return strdup(salt);
}

char* HashPasswd(const char *passwd, char *salt)
{
    // 生成随机盐值
    salt = GenerateSalt();
    int newLen = strlen(passwd) + strlen(salt) + 1;
    char* newPasswd = (char *)malloc(newLen);
    if (newPasswd == NULL)
    {
        printf("AddNewUser malloc error\n");
        return NULL;
    }
    memset(newPasswd, 0, newLen);
    strcat(newPasswd, passwd);
    strcat(newPasswd, salt);

    // 哈希处理
    unsigned char hashPasswd[SHA256_DIGEST_LENGTH] = { 0 };
    SHA256(newPasswd, strlen(newPasswd), hashPasswd);

    char result[SHA256_DIGEST_LENGTH] = { 0 };
    for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        char temp[8] = { 0 };
        sprintf(temp, "%x", hashPasswd[i]);// 将hashPasswd的每个字节转换为2位的16进制字符串
        strcat(result, temp);
    }

    // 释放内存
    free(newPasswd);
    return strdup(result);

}

// 添加新用户：未被注册，得保存到数据库里
bool AddNewUser(const char *name, const char *passwd)
{
    char *salt = GenerateSalt();
    char *result = HashPasswd(passwd, GenerateSalt());
    char sql[1024] = { 0 };
    sprintf(sql, "insert into user values('%s','%s', '%s');", name, result, salt);
    free(salt);
    free(result);
    return SQLExec(s, sql);
}

// 获取用户的盐
char* GetUserSalt(const char *name)
{
    char sql[1024] = { 0 };
    sprintf(sql, "select salt from user where name = '%s';", name);// 
    char **result = GetTableInfo(s, sql, NULL, NULL);
    if (result == NULL)
        return NULL;
    char *salt = strdup(result[1]);// 
    FreeTableInfo(result);
    return salt;
}

// 登录用户是否在表里
bool IsAccountEqual(const char *name, const char *passwd)
{
    char sql[1024] = { 0 };
    char *salt = GetUserSalt(name);
    if (salt == NULL)
        return NULL;
    char *hashpasswd = HashPasswd(passwd, NULL);
    sprintf(sql, "select count(*) from user where name = '%s' and passwd = '%s';", name, hashpasswd);
    free(hashpasswd);
    free(salt);

    char **result = GetTableInfo(s, sql, NULL, NULL);
    if (result == NULL)
        return false;
    int count = atoi(result[1]);
    FreeTableInfo(result);
    return count != 0;
}
